// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_AABB__
#define __H_MK_AABB__

namespace MK3DE
{
	struct MK3DE_API AABB
	{
		D3DXVECTOR3 minPt;
		D3DXVECTOR3 maxPt;

		AABB() : minPt(MK_MAX_FLOAT, MK_MAX_FLOAT, MK_MAX_FLOAT), maxPt(MK_MIN_FLOAT, MK_MIN_FLOAT, MK_MIN_FLOAT) { }
		AABB(const AABB& other) : minPt(other.minPt), maxPt(other.maxPt) { }

		explicit AABB(const D3DXVECTOR3* points, DWORD n) : minPt(MK_MAX_FLOAT, MK_MAX_FLOAT, MK_MAX_FLOAT), maxPt(MK_MIN_FLOAT, MK_MIN_FLOAT, MK_MIN_FLOAT)
		{
			for (DWORD i = 0; i < n; i++)
				Merge(&points[i]);
		}

		explicit AABB(const std::vector<D3DXVECTOR3>* points) : minPt(MK_MAX_FLOAT, MK_MAX_FLOAT, MK_MAX_FLOAT), maxPt(MK_MIN_FLOAT, MK_MIN_FLOAT, MK_MIN_FLOAT)
		{
			for (DWORD i = 0; i < points->size(); i++)
				Merge(&(*points)[i]);
		}

		explicit AABB(const std::vector<AABB>* boxes) : minPt(MK_MAX_FLOAT, MK_MAX_FLOAT, MK_MAX_FLOAT), maxPt(MK_MIN_FLOAT, MK_MIN_FLOAT, MK_MIN_FLOAT) 
		{
			for (DWORD i=0; (DWORD)i < boxes->size(); i++) 
			{
				Merge(&(*boxes)[i].maxPt);
				Merge(&(*boxes)[i].minPt);
			}
		}

		void Clear() { minPt = D3DXVECTOR3(MK_MAX_FLOAT, MK_MAX_FLOAT, MK_MAX_FLOAT); maxPt = D3DXVECTOR3(MK_MIN_FLOAT, MK_MIN_FLOAT, MK_MIN_FLOAT); }
		void Centroid(D3DXVECTOR3* vec) const { *vec = 0.5f * (minPt+maxPt); }
		void Merge(const D3DXVECTOR3* vec);
		void Merge(const AABB* aabb);
		BOOL Intersect(float* hitDist, const D3DXVECTOR3* origPt, const D3DXVECTOR3* dir);

		D3DXVECTOR3 Point(int i) const { return D3DXVECTOR3( (i & 1) ? minPt.x : maxPt.x, (i & 2) ? minPt.y : maxPt.y, (i & 4) ? minPt.z : maxPt.z ); }
		void Extract(D3DXVECTOR3 point[], int len);
	};

};

#endif // __H_MK_AABB__
